#include "ui_color.h"
#include "ui_error.h"
#include "ui_std_ex.h"
#include <algorithm>

namespace UI
{

UI_Color::UI_Color(const Uint32* pColorValue, const SDL_PixelFormat* pFormat)
{
	red = stdex::safe_static_cast<unsigned char>((pFormat->Rmask & *pColorValue) >> pFormat->Rshift);
	green = stdex::safe_static_cast<unsigned char>((pFormat->Gmask & *pColorValue) >> pFormat->Gshift);
	blue = stdex::safe_static_cast<unsigned char>((pFormat->Bmask & *pColorValue) >> pFormat->Bshift);
	alpha = stdex::safe_static_cast<unsigned char>((pFormat->Amask & *pColorValue) >> pFormat->Ashift);
}

UI_Color::UI_Color(std::string sColor) :
	alpha(0xFF)
{
	std::transform(sColor.begin(), sColor.end(), sColor.begin(), toupper);

	if (sColor == "WHITE")
	{
		red = 0xFF;
		green = 0xFF;
		blue = 0xFF;
	}
	else if (sColor == "LIGHTGRAY")
	{
		red = 0xC0;
		green = 0xC0;
		blue = 0xC0;
	}
	else if (sColor == "BLACK")
	{
		red = 0x00;
		green = 0x00;
		blue = 0x00;
	}
	else
	{
		std::vector<std::string> ColorStrings = stdex::DetokenizeString(sColor, ",");
		if (ColorStrings.size() >= 3)
		{
			red = stdex::safe_static_cast<unsigned char>(stdex::atoi(ColorStrings[0]));
			green = stdex::safe_static_cast<unsigned char>(stdex::atoi(ColorStrings[1]));
			blue = stdex::safe_static_cast<unsigned char>(stdex::atoi(ColorStrings[2]));
			if (ColorStrings.size() >= 4)
			{
				alpha = stdex::safe_static_cast<unsigned char>(stdex::atoi(ColorStrings[3]));
			}
		}
		else
		{
			throw(UI_Ex_App("KTV_Color::CRGBColor : Unable to instantiate KTV_Color from string."));
		}
	}
}


UI_Color& UI_Color::operator=(const UI_Color& c)
{
	red = c.red;
	green = c.green;
	blue = c.blue;
	alpha = c.alpha;
	return *this;
}


UI_Color UI_Color::operator+(const UI_Color& c) const
{
	double c1_ratio = stdex::safe_static_cast<double>(alpha) / 0xFF;
	double c2_ratio = stdex::safe_static_cast<double>(c.alpha) / 0xFF;
	double new_red = red * c1_ratio + c.red * c2_ratio;
	if (new_red > 255)
	{
		new_red = 255;
	}
	double new_green = green * c1_ratio + c.green * c2_ratio;
	if (new_green > 255)
	{
		new_green = 255;
	}
	double new_blue = blue * c1_ratio + c.blue * c2_ratio;
	if (new_blue > 255)
	{
		new_blue = 255;
	}
	double new_alpha = alpha + c.alpha;
	if (new_alpha > 255)
	{
		new_alpha = 255;
	}
	return UI_Color(stdex::safe_static_cast<unsigned char>(new_red), stdex::safe_static_cast<unsigned char>(new_green),
		stdex::safe_static_cast<unsigned char>(new_blue), stdex::safe_static_cast<unsigned char>(new_alpha));
}


UI_Color UI_Color::operator|(const UI_Color& c) const
{
	return UI_Color(red | c.red, green | c.green, blue | c.blue, alpha | c.alpha);
}


UI_Color UI_Color::operator&(const UI_Color& c) const
{
	return UI_Color(red & c.red, green & c.green, blue & c.blue, alpha & c.alpha);
}


UI_Color UI_Color::operator^(const UI_Color& c) const
{
	return UI_Color(red ^ c.red, green ^ c.green, blue ^ c.blue, alpha ^ c.alpha);
}


UI_Color UI_Color::MixNormal(const UI_Color& c) const
{
	double fg_ratio = stdex::safe_static_cast<double>(c.alpha) / 0xFF;
	double bg_ratio = stdex::safe_static_cast<double>(1.0 - fg_ratio);
	char new_red = stdex::safe_static_cast<unsigned char>(floor(red * bg_ratio + c.red * fg_ratio));
	char new_green = stdex::safe_static_cast<unsigned char>(floor(green * bg_ratio + c.green * fg_ratio));
	char new_blue = stdex::safe_static_cast<unsigned char>(floor(blue * bg_ratio + c.blue * fg_ratio));
	return UI_Color(new_red, new_green, new_blue, alpha);
}



UI_Color DEFAULT_BACKGROUND_COLOR = UI_Color(0x60, 0x60, 0x60);
UI_Color DEFAULT_FOREGROUND_COLOR = UI_Color(0xA0, 0xA0, 0xA0);
UI_Color DEFAULT_LINE_COLOR = UI_Color(0x00, 0x00, 0x00);
UI_Color DEFAULT_DISABLED_LINE_COLOR = UI_Color(0x40, 0x40, 0x40);
UI_Color COLOR_TRANSPARENT = UI_Color(0x00, 0x00, 0x00, 0x00);
UI_Color COLOR_WHITE = UI_Color(0xFF, 0xFF, 0xFF);
UI_Color COLOR_LIGHTGRAY = UI_Color(0xC0, 0xC0, 0xC0);
UI_Color COLOR_GRAY = UI_Color(0x80, 0x80, 0x80);
UI_Color COLOR_DARKGRAY = UI_Color(0x40, 0x40, 0x40);
UI_Color COLOR_BLACK = UI_Color(0x00, 0x00, 0x00);
UI_Color COLOR_BLUE = UI_Color(0x00, 0x00, 0xFF);
UI_Color COLOR_RED = UI_Color(0xFF, 0x00, 0x00);
UI_Color COLOR_GREEN = UI_Color(0x00, 0xFF, 0x00);
UI_Color COLOR_YELLOW = UI_Color(0xFF, 0xFF, 0x00);
UI_Color COLOR_CYAN = UI_Color(0x00, 0xFF, 0xFF);
UI_Color COLOR_MAGENTA = UI_Color(0xFF, 0x00, 0xFF);
UI_Color COLOR_SPECIAL = UI_Color(232,23,20);

}

